@node Using Scheme records in C
@section Using Scheme records in C

External C code can create records and access record slots positionally
using these functions & macros.  Note, however, that named access to
record fields is not supported, only indexed access, so C code must be
synchronized carefully with the corresponding Scheme that defines
record types.

@deftypefn {C function (may GC)} s48_value s48_make_record (s48_value @var{record-type})
@deftypefnx {C macro} int S48_RECORD_P (s48_value @var{object})
@deftypefnx {C macro} s48_value S48_RECORD_TYPE (s48_value @var{record})
@deftypefnx {C macro} s48_value S48_RECORD_REF (s48_value @var{record}, long @var{index})
@deftypefnx {C macro} void S48_RECORD_SET (s48_value @var{record}, long @var{index}, s48_value @var{value})
@deftypefnx {C function} void s48_check_record_type (s48_value @var{record}, s48_value @var{type-binding})
@code{s48_make_record} allocates a record on Scheme's heap with the
given record type; its arguments must be a shared binding whose value
is a record type descriptor (@pxref{Records}).    @code{S48_RECORD_P}
is the type predicate for records.  @code{S48_RECORD_TYPE} returns the
record type descriptor of @var{record}.  @code{S48_RECORD_REF} &
@code{S48_RECORD_SET} operate on records similarly to how
@code{S48_VECTOR_REF} & @code{S48_VECTOR_SET} work on vectors.
@code{s48_check_record_type} checks whether @var{record} is a record
whose type is the value of the shared binding @var{type_binding}.  If
this is not the case, it signals an exception.  (It also signals an
exception if @var{type_binding}'s value is not a record.)  Otherwise,
it returns normally.
@end deftypefn

For example, with this record type definition:

@lisp
(define-record-type thing :thing
  (make-thing a b)
  thing?
  (a thing-a)
  (b thing-b))@end lisp

@noindent
the identifier @code{:thing} is bound to the record type and can be
exported to C thus:

@lisp
(define-exported-binding "thing-record-type" :thing)@end lisp

@noindent
and @code{thing} records can be made in C:

@example
static s48_value thing_record_type = S48_FALSE;
void initialize_things(void)
@{
  S48_GC_PROTECT_GLOBAL(thing_record_type);
  thing_record_type = s48_get_imported_binding("thing-record-type");
@}

s48_value make_thing(s48_value a, s48_value b)
@{
  s48_value thing;

  S48_DECLARE_GC_PROTECT(2);
  S48_GC_PROTECT_2(a, b);

  thing = s48_make_record(thing_record_type);
  S48_RECORD_SET(thing, 0, a);
  S48_RECORD_SET(thing, 1, b);

  S48_GC_UNPROTECT();

  return thing;
@}@end example

@noindent
Note that the variables @code{a} & @code{b} must be protected against
the possibility of a garbage collection occurring during the call to
@code{s48_make_record}.
